/**
  ******************************************************************************
  * @file    MPU6050_Config.c
  * @brief   MPU6050六轴传感器(I2C接口)驱动实现
  * @author  18408107475@163.com
  * @version V1.0
  * @date    2025-7-15
  * @note    硬件特性：
  *          - 三轴加速度计(±2/±4/±8/±16g)
  *          - 三轴陀螺仪(±250/±500/±1000/±2000°/s)
  *          - 数字运动处理器(DMP)支持9轴融合
  *          - I2C接口(400kHz)，可选SPI(1MHz)
  *          - 内置温度传感器
  *          - 工作电压：2.375V-3.46V
  *
  * @attention 移植说明：
  *          1. 硬件连接：
  *             - SCL：PB6 (需4.7K上拉电阻)
  *             - SDA：PB7 (需4.7K上拉电阻)
  *             - AD0：接地(I2C地址0x68)或接VCC(地址0x69)
  *          2. 软件适配：
  *             - 修改I2C_GPIO_Config()中的端口定义
  *             - 调整Delay_ms()为实际平台的毫秒延时
  *             - 确保I2C通信速率≤400kHz
  ******************************************************************************
  */

#include "MPU6050_Config.h"  // 包含MPU6050寄存器定义、函数声明及依赖库

/**
  * @brief  向MPU6050指定寄存器写入单字节数据
  * @param  Reg_Address: 目标寄存器地址（8位，如PWR_MGMT_1=0x6B）
  * @param  I2C_Data: 待写入的8位数据（如0x01）
  * @retval true: 写入成功，false: 写入失败（I2C通信超时或从机无应答）
  * @note   底层依赖I2C总线驱动，自动处理设备地址（MPU6050_SLAVE_ADDRESS）
  *         通信流程：I2C起始→设备地址（写）→寄存器地址→数据→停止
  */
bool MPU6050_Write_Data(u8 Reg_Address, u8 I2C_Data)
{
    // 调用底层I2C写函数：设备地址+寄存器地址+数据
    return I2C_Write_Data(MPU6050_SLAVE_ADDRESS, Reg_Address, I2C_Data);
}

/**
  * @brief  从MPU6050指定寄存器读取单字节数据
  * @param  Reg_Address: 目标寄存器地址（8位，如WHO_AM_I=0x75）
  * @retval 读取到的8位数据（如0x68）；失败时返回0（需结合实际寄存器默认值判断）
  * @note   底层依赖I2C总线驱动，自动处理设备地址
  *         通信流程：I2C起始→设备地址（写）→寄存器地址→重复起始→设备地址（读）→数据→停止
  */
u8 MPU6050_Read_Data(u8 Reg_Address)
{
    // 调用底层I2C读函数：设备地址+寄存器地址→返回数据
    return I2C_Read_Data(MPU6050_SLAVE_ADDRESS, Reg_Address);
}

/**
  * @brief  初始化MPU6050传感器，配置工作参数
  * @note   初始化流程：
  *         1. 上电延时：等待传感器电源稳定（200ms）
  *         2. I2C总线初始化：配置GPIO和I2C外设（100kHz）
  *         3. 传感器配置延时：等待I2C总线稳定（200ms）
  *         4. 寄存器配置：
  *            - 电源管理：解除休眠，选择时钟源
  *            - 采样率：设置为100Hz
  *            - 滤波器：低通滤波带宽5Hz
  *            - 量程：加速度计±16g，陀螺仪±2000°/s
  */
void MPU6050_Config(void)
{
    Delay_ms(200);  // 传感器上电延时，确保电源稳定（推荐≥100ms）

    I2C_Config();   // 初始化I2C总线（GPIO复用开漏+100kHz速率）

    Delay_ms(200);  // I2C初始化后延时，等待总线状态稳定
	
    // 配置电源管理寄存器
    MPU6050_Write_Data(PWR_MGMT_1, 0x01);  // 解除休眠（BIT6=0），选择陀螺仪X轴作为时钟源（BIT2-0=001）
    MPU6050_Write_Data(PWR_MGMT_2, 0x00);  // 启用所有轴（默认值，BIT5-0=000000）

    // 配置采样率和滤波器
    MPU6050_Write_Data(SMPLRT_DIV, 0x09);  // 采样率分频：采样率=陀螺仪输出率/(SMPLRT_DIV+1)=1kHz/(9+1)=100Hz
    MPU6050_Write_Data(CONFIG, 0x06);      // 数字低通滤波器：DLPF_CFG=011→带宽5Hz，延迟98ms（滤除高频噪声）

    // 配置陀螺仪量程(±2000°/s)
    MPU6050_Write_Data(GYRO_CONFIG, 0x18);  // FS_SEL=11（BIT4-3=11）→ ±2000°/s，灵敏度16.4 LSB/(°/s)

    // 配置加速度计量程(±16g)
    MPU6050_Write_Data(ACCEL_CONFIG, 0x18);  // AFS_SEL=11（BIT4-3=11）→ ±16g，灵敏度2048 LSB/g
}

/**
  * @brief  获取MPU6050设备ID
  * @retval 设备ID（8位，正常为0x68，与AD0引脚无关）
  * @note   读取WHO_AM_I寄存器（0x75）的值，用于验证I2C通信是否正常：
  *         - 返回0x68：通信正常
  *         - 返回0xFF或其他值：I2C总线故障或传感器未连接
  */
u8 MPU6050_GetID(void)
{
    return MPU6050_Read_Data(WHO_AM_I);  // 读取设备ID寄存器
}

/**
  * @brief  读取MPU6050的六轴原始数据（加速度计+陀螺仪）
  * @param  AccX,AccY,AccZ: 加速度计X/Y/Z轴原始数据指针（16位有符号整数）
  * @param  GyroX,GyroY,GyroZ: 陀螺仪X/Y/Z轴原始数据指针（16位有符号整数）
  * @note   数据格式：
  *         - 每个轴数据由两个8位寄存器组成（高8位+低8位），如AccX = (ACCEL_XOUT_H << 8) | ACCEL_XOUT_L
  *         - 原始值范围：-32768 ~ 32767（16位补码）
  *         - 物理单位转换：
  *           加速度(g) = 原始值 / 2048（±16g量程）
  *           角速度(°/s) = 原始值 / 16.4（±2000°/s量程）
  * @读取顺序：按寄存器地址递增读取，确保数据同步性
  */
void MPU6050_GetData(int16_t *AccX, int16_t *AccY, int16_t *AccZ, 
                     int16_t *GyroX, int16_t *GyroY, int16_t *GyroZ)
{
    u8 DataH, DataL;  // 存储寄存器高8位和低8位数据
    
    // 读取加速度计X轴数据（ACCEL_XOUT_H=0x3B, ACCEL_XOUT_L=0x3C）
    DataH = MPU6050_Read_Data(ACCEL_XOUT_H);
    DataL = MPU6050_Read_Data(ACCEL_XOUT_L);
    *AccX = (DataH << 8) | DataL;  // 合并为16位有符号整数（如0x0123→291）
    
    // 读取加速度计Y轴数据（ACCEL_YOUT_H=0x3D, ACCEL_YOUT_L=0x3E）
    DataH = MPU6050_Read_Data(ACCEL_YOUT_H);
    DataL = MPU6050_Read_Data(ACCEL_YOUT_L);
    *AccY = (DataH << 8) | DataL;
    
    // 读取加速度计Z轴数据（ACCEL_ZOUT_H=0x3F, ACCEL_ZOUT_L=0x40）
    DataH = MPU6050_Read_Data(ACCEL_ZOUT_H);
    DataL = MPU6050_Read_Data(ACCEL_ZOUT_L);
    *AccZ = (DataH << 8) | DataL;
    
    // 读取陀螺仪X轴数据（GYRO_XOUT_H=0x43, GYRO_XOUT_L=0x44）
    DataH = MPU6050_Read_Data(GYRO_XOUT_H);
    DataL = MPU6050_Read_Data(GYRO_XOUT_L);
    *GyroX = (DataH << 8) | DataL;
    
    // 读取陀螺仪Y轴数据（GYRO_YOUT_H=0x45, GYRO_YOUT_L=0x46）
    DataH = MPU6050_Read_Data(GYRO_YOUT_H);
    DataL = MPU6050_Read_Data(GYRO_YOUT_L);
    *GyroY = (DataH << 8) | DataL;
    
    // 读取陀螺仪Z轴数据（GYRO_ZOUT_H=0x47, GYRO_ZOUT_L=0x48）
    DataH = MPU6050_Read_Data(GYRO_ZOUT_H);
    DataL = MPU6050_Read_Data(GYRO_ZOUT_L);
    *GyroZ = (DataH << 8) | DataL;
}